/**
 * @created March 20, 2007
 * 
 * @author csamson
 * @author tlopez
 *
 * @modified adegomme 13/04/07 : frequencies added
 *
 * This classe is a format used by IHM to communicate informations
 * about a SensorNetwork to the Simulator
 */
package kernel;

import java.util.*;
import objects.Station;
import objects.distribution.*;
import sleeping.*;
import comRadiusController.*;
import utils.*;
import java.awt.*;

public class DataSensorNetwork extends DataType{

    transient private String _name;

    transient private Color _color;
    public final static Color COLOR_DEF = new Color(70,155,255);

    //Coordonate of the upper left corner of the SensorNetwork Area
    transient private double _coordX;
    public final static double COORD_X_MIN = 0.0;
    public final static double COORD_X_DEF = 0.0;
    public double COORD_X_MAX;
    
    transient private double _coordY;
    public final static double COORD_Y_MIN = 0.0;
    public final static double COORD_Y_DEF = 0.0;
    public double COORD_Y_MAX;

    // Width and length of the SensorNetwork Area
    private double _width;
    public final static double WIDTH_MIN = 0.0;
    public final static double WIDTH_DEF = 0.0;
    public double WIDTH_MAX;
    
    private double _height;
    public final static double HEIGHT_MIN = 0.0;
    public final static double HEIGHT_DEF = 0.0;
    public double HEIGHT_MAX;

    private int _kCover;
    public final static int K_DEF = 1;
    public final static int K_MIN = 1;
    public final static int K_MAX = 10;
    
    private int _amount;
    public final static int AMOUNT_DEF = 1;
    public final static int AMOUNT_MIN = 1;
    public final static int AMOUNT_MAX = 200;

    private int _sleepingPeriod;
    public final static int SLP_PERIOD_DEF = 1000;
    public final static int SLP_PERIOD_MIN = 1;
    public final static int SLP_PERIOD_MAX = 100000;


    // sleeping strategy 
    public SleepingAlgo _sleepingAlgo;
    public static SleepingAlgo SLEEP_DEF = new NoSleepingAlgo();
    public final static String SLEEP_PACK = "sleeping";
    public final static String SLEEP_INTER = "SleepingAlgo";
    
    // distribution strategy 
    public DistributionAlgo _distributionAlgo;
    public static DistributionAlgo DISTRIB_DEF = new RandomDistribAlgo();
    public final static String DISTRIB_PACK = "objects.distribution";
    public final static String DISTRIB_INTER = "DistributionAlgo";

    // DataSensor representing the prototype of the sensor of this SensorNetwork
    public DataSensor _sensor;
    public final static DataSensor SENSOR_DEF = new DataSensor();

    // General probes for the network
    public Vector _probes; 
    
    /**
     * Default constructor
     */
    public DataSensorNetwork(){
	setName("");
	setCoordX(COORD_X_DEF);
	setCoordY(COORD_Y_DEF);
	setWidth(WIDTH_DEF);
	setHeight(HEIGHT_DEF);
	setColor(COLOR_DEF);
	setAmount(AMOUNT_DEF);
	setDistributionAlgo(DISTRIB_DEF);
	setProbes(new Vector());
	setSleepingAlgo(SLEEP_DEF);
	setSleepingPeriod(SLP_PERIOD_DEF);
	setKCover(K_DEF);
	setDataSensor(SENSOR_DEF);
    }

    /**
     */
    public DataSensorNetwork (
			      String name,
			      double x,
			      double y,
			      double w,
			      double l,
			      int a,
			      DistributionAlgo distrib,
			      Vector probes,
			      SleepingAlgo sleepingAlgo,
			      int slp_period,
			      int kcover,
			      DataSensor sensor ) {
	setName(name);
	setCoordX(x);
	setCoordY(y);
	setWidth(w);
	setHeight(l);
	setAmount(a);
	setDistributionAlgo(distrib);
	setProbes(probes);
	setSleepingAlgo(sleepingAlgo);
	setSleepingPeriod(slp_period);
	setKCover(kcover);
	setDataSensor(sensor);
    }
	
	
	
    public boolean setName(String name)
    {
	_name = name;
	return true;
    }
    
    public String getName()
    {
	return _name;
    }

    public boolean setColor(Color color)
    {
	_color = color;
	return true;
    }

    public Color getColor()
    {
	return _color;
    }
    
    public boolean setCoordX(double x)
    {
	boolean done = false;
	COORD_X_MAX = Simulator.getSimulator().getEnvironment().getSpace().getWidth();
	if(checkBounds(COORD_X_MIN,COORD_X_MAX,x)){
	    _coordX = x;
	    done = true;
	}else{
	    _coordX = COORD_X_DEF;
	}
	return done;
    }
    
    public double getCoordX()
    {
	return _coordX;
    }
    
    public boolean setCoordY(double y)
    {
	boolean done = false;
	COORD_Y_MAX = Simulator.getSimulator().getEnvironment().getSpace().getHeight();
	if(checkBounds(COORD_Y_MIN,COORD_Y_MAX,y)){
	    _coordY = y;
	    done = true;
	}else{
	    _coordY = COORD_Y_DEF;
	}
	return done;
    }
    
    public double getCoordY()
    {
	return _coordY;
    }
    
    public boolean setWidth(double w)
    {
	boolean done = false;
	WIDTH_MAX = Simulator.getSimulator().getEnvironment().getSpace().getWidth();
	if(checkBounds(WIDTH_MIN,WIDTH_MAX,w)){
	    _width = w;
	    done = true;
	}else{
	    _width = WIDTH_DEF;
	}
	return done;
    }
    
    public double getWidth()
    {
	return _width;
    }

    public boolean setHeight(double l)
    {
	boolean done = false;
	HEIGHT_MAX = Simulator.getSimulator().getEnvironment().getSpace().getHeight();
	if(checkBounds(HEIGHT_MIN,HEIGHT_MAX,l)){
	    _height = l;
	    done = true;
	}else{
	    _height = HEIGHT_DEF;
	}
	return done;
    }
    
    public double getHeight()
    {
	return _height;
    }

    public boolean setProbes(Vector probes)
    {
	_probes = new Vector(probes);
	return true;
    }

    public Vector getProbes()
    {
	return _probes;
    }

    public boolean setSleepingAlgo(String s){
	try{
	    Class sleepingAlgoClass = Class.forName(SLEEP_PACK + "." + s);
	    SleepingAlgo algo = (SleepingAlgo)(sleepingAlgoClass.newInstance());
	    return setSleepingAlgo(algo);
	}catch(Exception e){
	    e.printStackTrace();
	    setSleepingAlgo(SLEEP_DEF);
	    return false;
	}	
    }

    public boolean setSleepingAlgo(SleepingAlgo s){
	StrategyChoser sc = new StrategyChoser(SLEEP_PACK);
	sc.checkSuperclass(SLEEP_INTER);
	Vector<Class> strategies = sc.getStrategies();
	
	for(Class availableStrategy : strategies){
	    try{
		SleepingAlgo sStrategy = (SleepingAlgo)(availableStrategy.newInstance());	   
	    }catch(InstantiationException e){
	    }catch(IllegalAccessException e){
	    }
	    
	    if(availableStrategy.getName().equals(s.getClass().getName())){
		_sleepingAlgo = s;
		return true;
	    }
	}
	_sleepingAlgo = SLEEP_DEF;
	Debug.getConfigLogger().warning("The sleeping Algorithm "+s+" doesn't match any available strategy, default sleeping algorithm will be used instead");
	return false;
    }

    public SleepingAlgo getSleepingAlgo(){
	return _sleepingAlgo;
    }
	
    public int getSleepingPeriod()
    {
	return _sleepingPeriod;
    }
    
    public boolean setSleepingPeriod(int period)
    {
	boolean done = false;
	if(checkBounds(SLP_PERIOD_MIN,SLP_PERIOD_MAX,period)){
	    _sleepingPeriod=period;
	    done =true;
	}else{
	    _sleepingPeriod = SLP_PERIOD_DEF;
	    done = false;
	}
	return done;
    }

    public boolean setDistributionAlgo(String s){
	try{
	    Class distribAlgoClass = Class.forName(DISTRIB_PACK + "." + s);
	    DistributionAlgo algo = (DistributionAlgo)(distribAlgoClass.newInstance());
	    return setDistributionAlgo(algo);
	}catch(Exception e){
	    setDistributionAlgo(DISTRIB_DEF);
	    return false;
	}	
    }

    public boolean setDistributionAlgo(DistributionAlgo s){
	StrategyChoser sc = new StrategyChoser(DISTRIB_PACK);
	sc.checkSuperclass(DISTRIB_INTER);
	Vector<Class> strategies = sc.getStrategies();
	
	for(Class availableStrategy : strategies){
	    try{
		DistributionAlgo sStrategy = (DistributionAlgo)(availableStrategy.newInstance());	   
	    }catch(InstantiationException e){
	    }catch(IllegalAccessException e){
	    }
	    
	    if(availableStrategy.getName().equals(s.getClass().getName())){
		_distributionAlgo = s;
		return true;
	    }
	}
	_distributionAlgo = DISTRIB_DEF;
	Debug.getConfigLogger().warning("The distribution Algorithm "+s+" doesn't match any available strategy, default distribution algorithm will be used instead");
	return false;
    }

    public DistributionAlgo getDistributionAlgo(){
	return _distributionAlgo;
    }    

    public int getKCover(){
	return _kCover;
    }

    public boolean setKCover(int k){
	boolean done = false;
	if(checkBounds(K_MIN,K_MAX,k)){
	    _kCover = k;
	    done =true;
	}else{
	    _kCover = K_DEF;
	    done = false;
	}
	return done;
    }

    public int getAmount(){
	return _amount;
    }
    
    public boolean setAmount(int a){
	boolean done = false;
	if(checkBounds(AMOUNT_MIN,AMOUNT_MAX,a)){
	    _amount = a;
	    done =true;
	}else{
	    _amount = AMOUNT_DEF;
	    done = false;
	}
	return done;
    }


    public boolean setDataSensor(DataSensor sensor){
	_sensor = sensor;
	return true;
    }

    public DataSensor getDataSensor(){
	return _sensor;
    }   
    
    /**
     * This method gives the string associated to a SensorNetwork
     */
    public String toString(){
	String s = "Sensor Network : name = " + _name;
	return s;
    }
}
